home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / mamesrc / src / amiga / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  36.4 KB  |  1,069 lines

  1. /**************************************************************************
  2.  *
  3.  * Copyright (C) 1999 Mats Eirik Hansen (mats.hansen@triumph.no)
  4.  *
  5.  * $Id: main.c,v 1.1 1999/04/28 18:54:28 meh Exp meh $
  6.  *
  7.  * $Log: main.c,v $
  8.  * Revision 1.1  1999/04/28 18:54:28  meh
  9.  * Initial revision
  10.  *
  11.  *
  12.  *************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <strings.h>
  16.  
  17. #include <clib/alib_protos.h>
  18.  
  19. #include <exec/types.h>
  20. #include <exec/memory.h>
  21. #include <exec/tasks.h>
  22. #include <dos/dos.h>
  23. #include <workbench/workbench.h>
  24. #include <libraries/asl.h>
  25. #include <libraries/gadtools.h>
  26. #include <cybergraphx/cybergraphics.h>
  27.  
  28. #include <inline/exec.h>
  29. #include <inline/dos.h>
  30. #include <inline/graphics.h>
  31. #include <inline/intuition.h>
  32. #include <inline/asl.h>
  33. #include <inline/gadtools.h>
  34. #include <inline/locale.h>
  35. #include <inline/timer.h>
  36.  
  37. #ifdef POWERUP
  38. #include <powerup/ppclib/interface.h>
  39. #include <powerup/ppclib/message.h>
  40. #include <powerup/ppclib/tasks.h>
  41. #include <powerup/ppclib/memory.h>
  42. #include <inline/ppc.h>
  43. #endif
  44.  
  45. #define CATCOMP_BLOCK
  46. #define CATCOMP_CODE
  47.  
  48. #include "main.h"
  49. #include "version.h"
  50. #include "audio.h"
  51. #include "video.h"
  52. #include "inputs.h"
  53. #include "config.h"
  54. #include "gui.h"
  55.  
  56. #include "osdepend.h"
  57. #include "driver.h"
  58. #include "file.h"
  59.  
  60. #define MIN_STACK (10*1024)
  61.  
  62. #define ITEM_NEW    0
  63. #define ITEM_SAVE_ILBM  1
  64. #define ITEM_ABOUT    3
  65. #define ITEM_QUIT   5
  66. #define NUM_ITEMS   6
  67.  
  68. void     Main(int argc, char **argv);
  69. void ASM RefreshHandler(struct Hook *hook REG(a0));
  70. void ASM MenuHandler(struct Hook *hook REG(a0), APTR null REG(a2), ULONG *itemnum REG(a1));
  71. void ASM IDCMPHandler(struct Hook *hook REG(a0), APTR null REG(a2), ULONG *imclass REG(a1));
  72. void     SaveILBM(void);
  73. void     ErrorRequest(LONG msg_id, ...);
  74.  
  75. void     StartGame(void);  /* In amiga/amiga.c. */
  76.  
  77. #ifdef POWERUP
  78. struct GameDriver **Drivers;
  79. #endif
  80.  
  81. LONG        MenuSelect[NUM_ITEMS];
  82. UBYTE       Channel[4];
  83. static LONG NewGame;
  84.  
  85. UBYTE       ChannelBuffer[8];
  86.  
  87. struct DosLibrary   *DOSBase    = NULL;
  88. struct Library      *GfxBase    = NULL;
  89. struct Library      *CyberGfxBase = NULL;
  90. struct IntuitionBase  *IntuitionBase  = NULL;
  91. struct Library      *GadToolsBase = NULL;
  92. struct Library      *AslBase    = NULL;
  93. struct Library      *KeymapBase   = NULL;
  94. struct Library      *UtilityBase  = NULL;
  95. struct Library      *TimerBase    = NULL;
  96.  
  97. #ifdef POWERUP
  98. struct Library      *PPCLibBase   = NULL;
  99. #endif
  100.  
  101. struct FileRequester  *FileRequester  = NULL;
  102.  
  103. LONG          Width;
  104. LONG          Height;
  105. struct Audio      *Audio;
  106. struct Video      *Video;
  107. struct Inputs     *Inputs;
  108. struct AChannelArray  *ChannelArray[2];
  109. struct VPixelArray    *PixelArray[2];
  110. struct VDirectArray   *DirectArray;
  111. LONG          CurrentArray  = 0;
  112. BYTE          *Keys;
  113. struct IPort      *Port1;
  114. struct IPort      *Port2;
  115. UBYTE         *DirectPixels;
  116. ULONG         DirectBytesPerRow;
  117.  
  118. struct timerequest    *TimerIO;
  119. struct MsgPort      TimerMP;
  120.  
  121. struct LocaleInfo   LocaleInfo;
  122.  
  123. static struct Hook    RefreshHook;
  124. static struct Hook    MenuHook;
  125. static struct Hook    IDCMPHook;
  126.  
  127. static struct StackSwapStruct StackSwapStruct;
  128.  
  129. static struct NewMenu NewMenu[] =
  130. {
  131.   { NM_TITLE, (STRPTR) MSG_MENU_GAME,      NULL, 0,  0,  NULL  },
  132.   { NM_ITEM,  (STRPTR) MSG_MENU_NEW,       "N",  0,  0,  NULL  },
  133.   { NM_ITEM,  (STRPTR) MSG_MENU_SAVE_ILBM, "S",  0,  0,  NULL  },
  134.   { NM_ITEM,  (STRPTR) NM_BARLABEL,        NULL, 0,  0,  NULL  },
  135.   { NM_ITEM,  (STRPTR) MSG_MENU_ABOUT,     "?",  0,  0,  NULL  },
  136.   { NM_ITEM,  (STRPTR) NM_BARLABEL,        NULL, 0,  0,  NULL  },
  137.   { NM_ITEM,  (STRPTR) MSG_MENU_QUIT,      "Q",  0,  0,  NULL  },
  138.   { NM_END,   NULL,                        NULL, 0,  0,  NULL  },
  139. };
  140.  
  141. static struct Menu *Menu;
  142.  
  143. struct IKeyMap KeyMap[] =
  144. {
  145.   { OSD_KEY_ESC,        IKEY_ESC       },  { OSD_KEY_1,      '1'         },
  146.   { OSD_KEY_2,          '2'            },  { OSD_KEY_3,      '3'         },
  147.   { OSD_KEY_4,          '4'            },  { OSD_KEY_5,      '5'         },
  148.   { OSD_KEY_6,          '6'            },  { OSD_KEY_7,      '7'         },
  149.   { OSD_KEY_8,          '8'            },  { OSD_KEY_9,      '9'         },
  150.   { OSD_KEY_0,          '0'            },  { OSD_KEY_MINUS,      '-'         },
  151.   { OSD_KEY_EQUALS,     '='            },  { OSD_KEY_BACKSPACE, IKEY_BACKSPACE    },
  152.   { OSD_KEY_TAB,        IKEY_TAB       },  { OSD_KEY_Q,      'q'         },
  153.   { OSD_KEY_W,          'w'            },  { OSD_KEY_E,      'e'         },
  154.   { OSD_KEY_R,          'r'            },  { OSD_KEY_T,      't'         },
  155.   { OSD_KEY_Y,          'y'            },  { OSD_KEY_U,      'u'         },
  156.   { OSD_KEY_I,          'i'            },  { OSD_KEY_O,      'o'         },
  157.   { OSD_KEY_P,          'p'            },  { OSD_KEY_OPENBRACE,  '('         },
  158.   { OSD_KEY_CLOSEBRACE, ')'            },  { OSD_KEY_ENTER,    IKEY_ENTER      },
  159.   { OSD_KEY_LCONTROL,   IKEY_CONTROL   },  { OSD_KEY_A,      'a'         },
  160.   { OSD_KEY_S,          's'            },  { OSD_KEY_D,      'd'         },
  161.   { OSD_KEY_F,          'f'            },  { OSD_KEY_G,      'g'         },
  162.   { OSD_KEY_H,          'h'            },  { OSD_KEY_J,      'j'         },
  163.   { OSD_KEY_K,          'k'            },  { OSD_KEY_L,      'l'         },
  164.   { OSD_KEY_COLON,      ':'            },  { OSD_KEY_QUOTE,    '"'         },
  165.   { OSD_KEY_TILDE,      '`'            },  { OSD_KEY_LSHIFT,   IKEY_LSHIFT     },
  166.   { OSD_KEY_Z,          'z'            },  { OSD_KEY_X,      'x'         },
  167.   { OSD_KEY_C,          'c'            },  { OSD_KEY_V,      'v'         },
  168.   { OSD_KEY_B,          'b'            },  { OSD_KEY_N,      'n'         },
  169.   { OSD_KEY_M,          'm'            },  { OSD_KEY_COMMA,    ','         },
  170.   { OSD_KEY_STOP,       '.'            },  { OSD_KEY_SLASH,    '/'         },
  171.   { OSD_KEY_RSHIFT,     IKEY_RSHIFT,   },  { OSD_KEY_ASTERISK, '*'         },
  172.   { OSD_KEY_ALT,        IKEY_RALT      },  { OSD_KEY_ALT,    IKEY_LALT     },
  173.   { OSD_KEY_SPACE,      ' '            },  { OSD_KEY_CAPSLOCK, IKEY_CAPSLOCK,    },
  174.   { OSD_KEY_F1,         IKEY_F1        },  { OSD_KEY_F2,     IKEY_F2       },
  175.   { OSD_KEY_F3,         IKEY_F3        },  { OSD_KEY_F4,     IKEY_F4       },
  176.   { OSD_KEY_F5,         IKEY_F5        },  { OSD_KEY_F6,     IKEY_F6       },
  177.   { OSD_KEY_F8,         IKEY_F8        },  { OSD_KEY_F9,     IKEY_F9       },
  178.   { OSD_KEY_F10,        IKEY_F10       },  { OSD_KEY_NUMLOCK,  IKEY_NONE     },
  179.   { OSD_KEY_SCRLOCK,    IKEY_NONE      },  { OSD_KEY_HOME,   IKEY_NONE     },
  180.   { OSD_KEY_UP,         IKEY_UP        },  { OSD_KEY_PGUP,   IKEY_NONE     },
  181.   { OSD_KEY_MINUS_PAD,  IKEY_MINUS_PAD },  { OSD_KEY_LEFT,   IKEY_LEFT     },
  182.   { OSD_KEY_5_PAD,      IKEY_5_PAD     },  { OSD_KEY_RIGHT,    IKEY_RIGHT      },
  183.   { OSD_KEY_PLUS_PAD,   IKEY_PLUS_PAD  },  { OSD_KEY_END,    IKEY_NONE     },
  184.   { OSD_KEY_DOWN,       IKEY_DOWN      },  { OSD_KEY_PGDN,   IKEY_NONE     },
  185.   { OSD_KEY_INSERT,     IKEY_NONE      },  { OSD_KEY_DEL,    IKEY_DEL      },
  186.   { OSD_KEY_F11,        IKEY_NONE      },  { OSD_KEY_F12,    IKEY_NONE     },
  187.   { OSD_KEY_F7,         IKEY_F7        },  { OSD_MAX_KEY,    IKEY_NONE     },
  188.   { 0,                  0              }
  189. };
  190.  
  191. int main(int argc, char **argv)
  192. {
  193.   struct Task *task;
  194.   
  195.   task  = FindTask(NULL);
  196.  
  197.   if((task->tc_SPReg - task->tc_SPLower) < (MIN_STACK - 1024))
  198.   {
  199.     StackSwapStruct.stk_Lower = AllocVec(MIN_STACK, MEMF_PUBLIC);
  200.     
  201.     if(StackSwapStruct.stk_Lower)
  202.     {
  203.       StackSwapStruct.stk_Upper = (ULONG) StackSwapStruct.stk_Lower + MIN_STACK;
  204.       StackSwapStruct.stk_Pointer = (APTR) StackSwapStruct.stk_Upper;
  205.  
  206.       StackSwap(&StackSwapStruct);
  207.       
  208.       Main(argc, argv);
  209.  
  210.       StackSwap(&StackSwapStruct);
  211.     }
  212.   }
  213.   else
  214.     Main(argc, argv);
  215.  
  216.   return(0);
  217. }
  218.  
  219. void Main(int argc, char **argv)
  220. {
  221.   ULONG i;
  222.   ULONG quit;
  223. #ifdef POWERUP
  224.   struct ASound     *sound;
  225.   void          *ppc_object;
  226.   void          *ppc_task;
  227.   void          *m68k_ports[2];
  228.   void          *ppc_port;
  229.   void          *ppc_msg;
  230.   void          *msg_startup;
  231.   void          *msg;
  232.   void          *port_list;
  233.   struct MsgStartupData *msg_startup_data;
  234.   LONG          *msg_data;
  235.   LONG          *ppc_msg_data;
  236.   LONG          ppc_msg_id;
  237.   LONG          reply;
  238. #endif
  239.   if((DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 39)))
  240.   {
  241.     if((GfxBase = OpenLibrary("graphics.library", 39)))
  242.     {
  243.       if((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39)))
  244.       {
  245.         if((UtilityBase = OpenLibrary("utility.library",0)))
  246.         {
  247.           if((KeymapBase = OpenLibrary("keymap.library", 36)))
  248.           {
  249.             if((AslBase = OpenLibrary("asl.library", 36)))
  250.             {
  251. #ifdef POWERUP
  252.               if((PPCLibBase = OpenLibrary("ppc.library", 46)))
  253.               {
  254. #endif
  255.  
  256.               CyberGfxBase  = OpenLibrary("cybergraphics.library", 0);
  257.  
  258.               GadToolsBase  = OpenLibrary("gadtools.library", 0);
  259.  
  260.               if(GadToolsBase)
  261.               {
  262.                 for(i = 0; NewMenu[i].nm_Type != NM_END; i++)
  263.                 {
  264.                   if(((NewMenu[i].nm_Type == NM_TITLE) || (NewMenu[i].nm_Type == NM_ITEM))
  265.                   && (NewMenu[i].nm_Label != NM_BARLABEL))
  266.                     NewMenu[i].nm_Label = GetMessage((LONG) NewMenu[i].nm_Label);
  267.                 }
  268.  
  269.                 Menu  = CreateMenus(NewMenu, GTMN_FullMenu, TRUE, TAG_END);
  270.               }
  271.               else
  272.                 Menu  = NULL;
  273.  
  274.               TimerBase   = NULL;
  275.  
  276.               TimerMP.mp_Node.ln_Type   = NT_MSGPORT;
  277.               TimerMP.mp_Flags      = PA_IGNORE;
  278.               NewList(&TimerMP.mp_MsgList);
  279.               
  280.               TimerIO = CreateIORequest(&TimerMP, sizeof(struct timerequest));
  281.               if(TimerIO)
  282.               {
  283.                 if(!OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) TimerIO, 0))
  284.                   TimerBase = (struct Library *) TimerIO->tr_node.io_Device;
  285.               }
  286.  
  287.               LocaleInfo.li_LocaleBase = NULL;    /* Locale support is not
  288.                                   ** implemented yet. */
  289.  
  290. #ifdef POWERUP
  291.               if(TimerBase)
  292.               {
  293. #ifndef MESS
  294.                 ppc_object = PPCLoadObject("mameppc.elf");
  295. #else
  296.                 ppc_object = PPCLoadObject("messppc.elf");
  297. #endif                  
  298.                 if(ppc_object)
  299.                 {
  300.                   m68k_ports[0] = PPCCreatePort(NULL);
  301.                   m68k_ports[1] = NULL;
  302.                   
  303.                   if(m68k_ports[0])
  304.                   {
  305.                     msg_startup = PPCCreateMessage(m68k_ports[0], sizeof(struct MsgStartupData));
  306.                     
  307.                     if(msg_startup)
  308.                     {
  309.                       msg = PPCCreateMessage(m68k_ports[0], M68k_MSGSIZE_MAX);
  310.  
  311.                       if(msg)                   
  312.                       {
  313.                         msg_startup_data = PPCAllocVec(sizeof(struct MsgStartupData), MEMF_ANY);
  314.  
  315.                         if(msg_startup_data)
  316.                         {
  317.                           msg_data = PPCAllocVec(M68k_MSGSIZE_MAX, MEMF_ANY);
  318.  
  319.                           if(msg_data)
  320.                           {
  321.                             msg_startup_data->M68kPort  = m68k_ports[0];
  322.                             msg_startup_data->Version = VERNUM;
  323.                             msg_startup_data->Revision  = REVNUM;
  324.                             
  325.                             ppc_task = PPCCreateTaskTags( ppc_object,
  326.                                             PPCTASKTAG_MSGPORT,       TRUE,
  327.                                             PPCTASKTAG_STARTUP_MSG,     (ULONG) msg_startup,
  328.                                             PPCTASKTAG_STARTUP_MSGDATA,   (ULONG) msg_startup_data,
  329.                                             PPCTASKTAG_STARTUP_MSGLENGTH, 0,
  330.                                             PPCTASKTAG_STARTUP_MSGID,   M68k_MSG_STARTUP,
  331.                                             PPCTASKTAG_STACKSIZE,     204800,
  332.                                             TAG_DONE);
  333.  
  334.                             if(ppc_task)
  335.                             {
  336.                               ppc_port = (void *) PPCGetTaskAttrsTags(ppc_task, PPCTASKINFOTAG_MSGPORT, 0, TAG_DONE);
  337.                               
  338.                               PPCWaitPort(m68k_ports[0]);
  339.                               ppc_msg = PPCGetMessage(m68k_ports[0]);
  340.                                                     
  341.                               if(ppc_msg != msg_startup)
  342.                               {
  343.                                 Drivers = (struct GameDriver **) PPCGetMessageAttr(ppc_msg, PPCMSGTAG_DATA);
  344.                                 
  345.                                 PPCReplyMessage(ppc_msg);
  346.                                 
  347.                                 CacheClearU();
  348.                             
  349.                                 /* Now it should be safe to access Drivers. */
  350. #endif
  351.                 quit = AllocConfig(argc, argv);
  352.                 
  353.                 if(!quit)
  354.                 {
  355.                   AllocGUI();
  356.                   LoadConfig(argc, argv);
  357.  
  358.                   if(Config[CFG_DRIVER] < 0)
  359.                   {
  360.                     GetConfig(0, Config);
  361.                     quit = MainGUI();
  362.                   }
  363.                   else
  364.                     quit = FALSE;
  365. #ifndef POWERUP
  366.                   while(!quit)
  367. #else
  368.                   while(1)
  369. #endif                    
  370.                   {
  371. #ifdef MESS
  372.                     GetConfig(Config[CFG_DRIVER], Config);
  373. #else
  374.                     GetConfig(Config[CFG_DRIVER]+2, Config);
  375.  
  376.                     if(Config[CFG_USEDEFAULTS])
  377.                     {   
  378.                       if(Drivers[Config[CFG_DRIVER]]->drv->video_attributes & VIDEO_TYPE_VECTOR)
  379.                         GetConfig(1, Config);
  380.                       else
  381.                         GetConfig(0, Config);
  382.                     }
  383. #endif
  384.                     
  385.                     NewGame     = 1;
  386.                     Inputs      = NULL;
  387.                     Keys      = NULL;
  388.                     Audio     = NULL;
  389.                     ChannelArray[0] = NULL;
  390.                     ChannelArray[1] = NULL;
  391.  
  392.                     if(!quit && (Config[CFG_SOUND] != CFGS_NO))
  393.                     {
  394.                       Audio = AllocAudio( AA_UseAHI,    (Config[CFG_SOUND] == CFGS_AHI) ? TRUE : FALSE,
  395.                                 AA_Channels,  AUDIO_CHANNELS,
  396.                                 AA_MaxSounds, 255,
  397.                                 AA_MinFreeChip, Config[CFG_MINFREECHIP]*1024,
  398.                                 TAG_END);
  399.                       
  400.                       if(Audio)
  401.                       {
  402.                         ChannelArray[0] = AAllocChannelArray(Audio, AUDIO_BUFFER_LENGTH);
  403. #ifdef POWERUP
  404.                         ChannelArray[1] = AAllocChannelArray(Audio, AUDIO_BUFFER_LENGTH);
  405. #endif
  406.                       }
  407.                     }
  408. #ifdef POWERUP
  409.                     msg_data[M68k_MSGDATA_CHANNELARRAY1]  = (LONG) ChannelArray[0];
  410.                     msg_data[M68k_MSGDATA_CHANNELARRAY2]  = (LONG) ChannelArray[1];
  411.  
  412.                     if(ChannelArray[0])
  413.                       msg_data[M68k_MSGDATA_CHANNELARRAYSIZE] = ChannelArray[0]->Size;
  414.  
  415.                     for(i = 0; i < CFG_ITEMS; i++)
  416.                       msg_data[M68k_MSGDATA_CONFIG + i] = Config[i];
  417.  
  418.                     if(quit)
  419.                     {
  420.                       PPCSendMessage(ppc_port, msg, 0, 0, M68k_MSG_CONFIG);
  421.                       PPCWaitPort(m68k_ports[0]);
  422.                       PPCGetMessage(m68k_ports[0]);
  423.                     }
  424.                     else
  425.                     {                   
  426.                       CacheClearU();
  427.                       
  428.                       PPCSendMessage(ppc_port, msg, msg_data, M68k_MSGSIZE_CONFIG, M68k_MSG_CONFIG);
  429.                       PPCWaitPort(m68k_ports[0]);
  430.                       PPCGetMessage(m68k_ports[0]);
  431.                     }
  432.  
  433.                     port_list = NULL;
  434.  
  435.                     do
  436.                     {
  437.                       if(port_list)
  438.                       {
  439.                         ppc_msg = PPCWaitPortList(port_list);
  440.                         
  441.                         i = PPCGetPortListAttr(port_list, PPCPORTLISTTAG_RECEIVEDSIGNALS);
  442.  
  443.                         if(i & Inputs->SignalMask)
  444.                           InputUpdate(FALSE);
  445.                       }
  446.                       else
  447.                         ppc_msg = PPCWaitPort(m68k_ports[0]);
  448.                       
  449.                       if(ppc_msg)
  450.                         ppc_msg = PPCGetMessage(m68k_ports[0]);
  451.  
  452.                       if(ppc_msg != msg_startup)
  453.                       {
  454.                         if(ppc_msg)
  455.                         {
  456.                           ppc_msg_id    = PPCGetMessageAttr(ppc_msg, PPCMSGTAG_MSGID);
  457.                           ppc_msg_data  = (LONG *) PPCGetMessageAttr(ppc_msg, PPCMSGTAG_DATA);
  458.                         
  459.                           switch(ppc_msg_id)
  460.                           {
  461.                             case PPC_MSG_VIDEOOPEN:
  462.                               msg_data[M68k_MSGDATA_RESULT] = VideoOpen(ppc_msg_data[PPC_MSGDATA_WIDTH],
  463.                                                                         ppc_msg_data[PPC_MSGDATA_HEIGHT],
  464.                                                                         ppc_msg_data[PPC_MSGDATA_LEFT],
  465.                                                                         ppc_msg_data[PPC_MSGDATA_TOP],
  466.                                                                         ppc_msg_data[PPC_MSGDATA_RIGHT],
  467.                                                                         ppc_msg_data[PPC_MSGDATA_BOTTOM],
  468.                                                                         ppc_msg_data[PPC_MSGDATA_DIRTY]);
  469.  
  470.                               PPCReplyMessage(ppc_msg);
  471.  
  472.                               if(msg_data[M68k_MSGDATA_RESULT])
  473.                               {
  474.                                 msg_data[M68k_MSGDATA_WIDTH]  = Width;
  475.                                 msg_data[M68k_MSGDATA_HEIGHT] = Height;
  476.  
  477.                                 msg_data[M68k_MSGDATA_PIXELARRAY1]      = (LONG) PixelArray[0];
  478.                                 msg_data[M68k_MSGDATA_PIXELARRAY2]      = (LONG) PixelArray[1];
  479.  
  480.                                 msg_data[M68k_MSGDATA_DIRECTARRAY]      = (LONG) DirectArray;
  481.  
  482.                                 msg_data[M68k_MSGDATA_KEYS]   = (LONG) Keys;
  483.                                 msg_data[M68k_MSGDATA_PORT1]  = (LONG) Port1;
  484.                                 msg_data[M68k_MSGDATA_PORT2]  = (LONG) Port2;
  485.                                 
  486.                                 port_list = PPCCreatePortList(m68k_ports, Inputs->SignalMask);
  487.                               }
  488.  
  489.                               PPCSendMessage(ppc_port, msg, msg_data, M68k_MSGSIZE_VIDEODATA, M68k_MSG_VIDEODATA);
  490.                               PPCWaitPort(m68k_ports[0]);
  491.                               PPCGetMessage(m68k_ports[0]);
  492.                               
  493.                               break;
  494.  
  495.                             case PPC_MSG_VIDEOCLOSE:
  496.                               PPCReplyMessage(ppc_msg);
  497.                               VideoClose();
  498.  
  499.                               if(port_list)
  500.                                 PPCDeletePortList(port_list);
  501.                               
  502.                               port_list = NULL;
  503.  
  504.                               break;
  505.  
  506.                             case PPC_MSG_INPUTUPDATE:
  507.                               InputUpdate(TRUE);
  508.                               PPCReplyMessage(ppc_msg);
  509.                               break;
  510.  
  511.                             case PPC_MSG_SETPIXELFRAME:
  512.                               if(Config[CFG_ASYNCPPC])
  513.                               {
  514.                                 PPCReplyMessage(ppc_msg);
  515.                               
  516.                                 PPCSendMessage(ppc_port, msg, (void *) ((VGetFrameSkip(Video)<<16)|VGetFPS(Video)), 0, M68k_MSG_FRAMEDATA);
  517.                                 PPCWaitPort(m68k_ports[0]);
  518.                                 PPCGetMessage(m68k_ports[0]);
  519.                               }
  520.  
  521.                               i = ((ULONG) ppc_msg_data) & 0xf;
  522.  
  523.                               VInvalidPixelArray(PixelArray[i]);
  524.  
  525.                               VSetFrameSkip(Video, (((LONG) ppc_msg_data) >> 4) & 0xf);
  526.                               VSetLimitSpeed(Video, (((LONG) ppc_msg_data) >> 8) & 0xf);
  527.  
  528.                               InputUpdate(FALSE);
  529.                               
  530.                               VSetPixelFrame(PixelArray[i]);
  531.                                 
  532.                               if(ChannelArray[0] && ChannelArray[1])
  533.                               {
  534.                                 PPCCacheInvalidE(ChannelArray[i], ChannelArray[i]->Size, CACRF_ClearD);
  535.                                 ASetChannelFrame(ChannelArray[i]);
  536.                               }
  537.  
  538.                               if(!Config[CFG_ASYNCPPC])
  539.                               {
  540.                                 PPCReplyMessage(ppc_msg);
  541.                               
  542.                                 PPCSendMessage(ppc_port, msg, (void *) ((VGetFrameSkip(Video)<<16)|VGetFPS(Video)), 0, M68k_MSG_FRAMEDATA);
  543.                                 PPCWaitPort(m68k_ports[0]);
  544.                                 PPCGetMessage(m68k_ports[0]);
  545.                               }
  546.                               break;
  547.  
  548.                             case PPC_MSG_SETDIRECTFRAME:
  549.                               PPCReplyMessage(ppc_msg);
  550.  
  551.                               if(ChannelArray[0] && ChannelArray[1])
  552.                               {
  553.                                 PPCCacheInvalidE(ChannelArray[i], ChannelArray[i]->Size, CACRF_ClearD);
  554.                                 ASetChannelFrame(ChannelArray[i]);
  555.                               }
  556.  
  557.                               i = ((ULONG) ppc_msg_data) & 0xf;
  558.                               
  559.                               VSetFrameSkip(Video, (((LONG) ppc_msg_data) >> 4) & 0xf);
  560.                               VSetLimitSpeed(Video, (((LONG) ppc_msg_data) >> 8) & 0xf);
  561.  
  562.                               InputUpdate(FALSE);
  563.                               
  564.                               VSetDirectFrame(DirectArray);
  565.                                                               
  566.                               PPCSendMessage(ppc_port, msg, (void *) ((VGetFrameSkip(Video)<<16)|VGetFPS(Video)), 0, M68k_MSG_FRAMEDATA);
  567.                               PPCWaitPort(m68k_ports[0]);
  568.                               PPCGetMessage(m68k_ports[0]);
  569.  
  570.                               break;
  571.  
  572.                             case PPC_MSG_OPENFILETYPE:
  573.                               reply = (LONG) OpenFileType(  (const char *) &ppc_msg_data[PPC_MSGDATA_DIRNAME],
  574.                                               (const char *) &ppc_msg_data[PPC_MSGDATA_FILENAME],
  575.                                               ppc_msg_data[PPC_MSGDATA_MODE],
  576.                                               ppc_msg_data[PPC_MSGDATA_TYPE]);
  577.                               PPCReplyMessage(ppc_msg);
  578.  
  579.                               PPCSendMessage(ppc_port, msg, (void *) reply, 0, M68k_MSG_FILE);
  580.                               PPCWaitPort(m68k_ports[0]);
  581.                               PPCGetMessage(m68k_ports[0]);
  582.                               break;
  583.                             
  584.                             case PPC_MSG_CLOSEFILE:
  585.                               PPCReplyMessage(ppc_msg);
  586.                               CloseFile((struct File *) ppc_msg_data);
  587.                               break;
  588.                             
  589.                             case PPC_MSG_READSOUND:
  590.                               PPCReplyMessage(ppc_msg);
  591.                               PPCSendMessage(ppc_port, msg, AReadSound(Audio, (BPTR) ppc_msg_data), 0, M68k_MSG_FILE);
  592.                               PPCWaitPort(m68k_ports[0]);
  593.                               PPCGetMessage(m68k_ports[0]);
  594.                               break;
  595.  
  596.                             case PPC_MSG_LOADSOUND:
  597.                               PPCCacheInvalidE((APTR) ppc_msg_data[PPC_MSGDATA_SAMPLE], ppc_msg_data[PPC_MSGDATA_LENGTH], CACRF_ClearD);
  598.                             
  599.                               sound = ALoadSound(Audio, (APTR) ppc_msg_data[PPC_MSGDATA_SAMPLE],
  600.                                             ppc_msg_data[PPC_MSGDATA_RESOLUTION],
  601.                                             ppc_msg_data[PPC_MSGDATA_LENGTH],
  602.                                             ppc_msg_data[PPC_MSGDATA_FREQUENCY],
  603.                                             ppc_msg_data[PPC_MSGDATA_VOLUME]);
  604.                               PPCReplyMessage(ppc_msg);
  605.  
  606.                               PPCSendMessage(ppc_port, msg, sound, 0, M68k_MSG_FILE);
  607.                               PPCWaitPort(m68k_ports[0]);
  608.                               PPCGetMessage(m68k_ports[0]);
  609.                               break;
  610.  
  611.                             case PPC_MSG_QUIT:
  612.                               PPCReplyMessage(ppc_msg);
  613.                               quit = TRUE;
  614.                               break;
  615.                           }
  616.                         }
  617.                       }
  618.                     } while((ppc_msg != msg_startup) && !quit);
  619. #else
  620.                     StartGame();
  621. #endif
  622.                     if(Audio)
  623.                       FreeAudio(Audio);
  624. #ifdef POWERUP
  625.                     if(ppc_msg == msg_startup)
  626.                       break;
  627. #endif                    
  628.                     if(NewGame > 0)
  629.                       quit = MainGUI();
  630.                     else if(!NewGame)
  631.                       quit = TRUE;
  632.                   }
  633.  
  634.                   FreeGUI();                  
  635.                 }
  636.  
  637.                 FreeConfig();
  638. #ifdef POWERUP
  639.                               }
  640.                             }
  641.                             else
  642.                               ErrorRequest(MSG_FAILED_TO_CREATE_PPC_TASK);
  643.  
  644.                             PPCFreeVec(msg_data);
  645.                           }
  646.  
  647.                           PPCFreeVec(msg_startup_data);
  648.                         }
  649.                         
  650.                         PPCDeleteMessage(msg);
  651.                       }
  652.  
  653.                       PPCDeleteMessage(msg_startup);
  654.                     }
  655.                     
  656.                     PPCDeletePort(m68k_ports[0]);
  657.                   }
  658.                   
  659.                   PPCUnLoadObject(ppc_object);
  660.                 }
  661.                 else
  662.                   ErrorRequest(MSG_FAILED_TO_LOAD_ELF);
  663.               }
  664. #endif
  665.               if(TimerIO)
  666.               {
  667.                 if(TimerBase)
  668.                   CloseDevice((struct IORequest *) TimerIO);
  669.                 DeleteIORequest((struct IORequest *) TimerIO);
  670.               }
  671.  
  672.               if(CyberGfxBase)
  673.                 CloseLibrary(CyberGfxBase);
  674.               if(GadToolsBase)
  675.                 CloseLibrary(GadToolsBase);
  676.               if(FileRequester) 
  677.                 FreeAslRequest(FileRequester);
  678.               CloseLibrary(AslBase);
  679.  
  680. #ifdef POWERUP
  681.                 CloseLibrary(PPCLibBase);
  682.               }
  683.               else
  684.                 ErrorRequest(MSG_REQUIRES_LIB, "ppc.library", 46);
  685. #endif
  686.             }
  687.             CloseLibrary(KeymapBase);
  688.           }
  689.           CloseLibrary(UtilityBase);
  690.         }
  691.         CloseLibrary((struct Library *) IntuitionBase);
  692.       }
  693.       CloseLibrary(GfxBase);
  694.     }
  695.     CloseLibrary((struct Library *) DOSBase);
  696.   }
  697. }
  698.  
  699. LONG VideoOpen(LONG width, LONG height, LONG left, LONG top, LONG right, LONG bottom, LONG dirty)
  700. {
  701.   static ULONG pixel_formats[] =
  702.   {
  703.     PIXFMT_RGB16,
  704.     PIXFMT_RGB15,
  705.     PIXFMT_BGR15,
  706.     PIXFMT_RGB15PC,
  707.     PIXFMT_BGR15PC,
  708.     PIXFMT_BGR16,
  709.     PIXFMT_RGB16PC,
  710.     PIXFMT_BGR16PC,
  711.     PIXFMT_LUT8,
  712.     ~0
  713.   };
  714.  
  715.   int  fail;
  716.   LONG visible_width;
  717.   LONG visible_height;
  718.  
  719.  
  720.   if(Config[CFG_DIRECTMODE] == CFGDM_DRAW)
  721.   {
  722.     visible_width  = width + 16;
  723.     visible_height = height + 16;
  724.   }
  725.   else
  726.   {
  727.     visible_width  = right - left + 1;
  728.     visible_height = bottom - top + 1;
  729.   }
  730.  
  731.   /* Disable dirty line support if requested by user. */
  732.  
  733.   if(!Config[CFG_DIRTYLINES])
  734.     dirty = 0;
  735.  
  736.   Video = AllocVideo(VA_UseScreen,     (Config[CFG_SCREENTYPE] != CFGST_WB),
  737.                      VA_UseScreenReq,  (Config[CFG_SCREENTYPE] == CFGST_USERSELECT),
  738.                      VA_Width,         (Config[CFG_WIDTH] > visible_width)
  739.                                        ? Config[CFG_WIDTH]
  740.                                        : visible_width,
  741.                      VA_Height,        (Config[CFG_HEIGHT] > visible_height)
  742.                                        ? Config[CFG_HEIGHT]
  743.                                        : visible_height,
  744.                      VA_ModeID,        (Config[CFG_SCREENTYPE] == CFGST_CUSTOM)
  745.                                        ? (Config[CFG_SCREENMODE])
  746.                                        : INVALID_ID,
  747.                      VA_Depth,         (Config[CFG_SCREENTYPE] == CFGST_CUSTOM)
  748.                                        ? (Config[CFG_DEPTH])
  749.                                        : 0,
  750.                      VA_Buffers,       Config[CFG_BUFFERING]+1,
  751.                      VA_Title,         APPNAME,
  752.                      VA_Menu,          Menu,
  753.                      VA_FPS,           Drivers[Config[CFG_DRIVER]]->drv->frames_per_second,
  754.                      VA_MaxColors,     (Drivers[Config[CFG_DRIVER]]->drv->total_colors < 256)
  755.                                        ? Drivers[Config[CFG_DRIVER]]->drv->total_colors
  756.                                        : ((Drivers[Config[CFG_DRIVER]]->drv->video_attributes & VIDEO_SUPPORTS_16BIT)
  757.                                          && Config[CFG_ALLOW16BIT])
  758.                                          ? (1<<16)
  759.                                          : 256,
  760.                      VA_AutoFrameSkip, Config[CFG_AUTOFRAMESKIP],
  761.                      VA_MaxFrameSkip,  4,
  762.                      TAG_END);
  763.  
  764.   if(Video)
  765.   {
  766.     DirectArray = NULL;
  767.     Inputs      = NULL;
  768.   
  769.     if(Config[CFG_DIRECTMODE])
  770.     {
  771.       DirectArray = VAllocDirectArray(Video, visible_width, visible_height);
  772.       
  773.       if(DirectArray)
  774.       {
  775.         VSetDirectFrame(DirectArray);
  776.         
  777.         if(!DirectArray->Pixels)
  778.         {
  779.           VFreeDirectArray(DirectArray);
  780.           DirectArray = NULL;
  781.         }
  782.       }
  783.     }
  784.  
  785.     fail = 0;
  786.  
  787.     if(!DirectArray)
  788.     {
  789.       if((Drivers[Config[CFG_DRIVER]]->drv->video_attributes & VIDEO_SUPPORTS_16BIT)
  790.          && Config[CFG_ALLOW16BIT])
  791.       {
  792.         PixelArray[0] = VAllocPixelArray(Video, width+16, height+16, dirty, pixel_formats);
  793.       }
  794.       else
  795.         PixelArray[0] = VAllocPixelArray(Video, width+16, height+16, dirty, NULL);
  796.       
  797.       if(PixelArray[0])
  798.       {
  799.         VSetPixelArrayBox(PixelArray[0], 8 + left, 8 + top, 8 + right, 8 + bottom);
  800.       }
  801.       else
  802.         fail = 1;
  803.     }
  804.     else
  805.       PixelArray[0] = NULL;
  806.  
  807. #ifdef POWERUP
  808.     if(!DirectArray)
  809.     {
  810.       if((Drivers[Config[CFG_DRIVER]]->drv->video_attributes & VIDEO_SUPPORTS_16BIT)
  811.          && Config[CFG_ALLOW16BIT])
  812.       {
  813.         PixelArray[1] = VAllocPixelArray(Video, width+16, height+16, dirty, pixel_formats);
  814.       }
  815.       else
  816.         PixelArray[1] = VAllocPixelArray(Video, width+16, height+16, dirty, NULL);
  817.  
  818.       if(PixelArray[1])
  819.       {
  820.         VSetPixelArrayBox(PixelArray[1], 8 + left, 8 + top, 8 + right, 8 + bottom);
  821.       }
  822.       else
  823.         fail = 1;
  824.     }
  825.     else
  826.       PixelArray[1] = NULL;
  827. #endif
  828.  
  829.     if(!fail)
  830.     {
  831.       RefreshHook.h_Entry = (HOOKFUNC) RefreshHandler;
  832.       MenuHook.h_Entry    = (HOOKFUNC) MenuHandler;
  833.       IDCMPHook.h_Entry   = (HOOKFUNC) IDCMPHandler;
  834.  
  835.       Inputs = AllocInputs(IA_Port1,          (Config[CFG_JOY1TYPE] == CFGJ1_MOUSE1)
  836.                                               ? IPT_MOUSE
  837.                                               : Config[CFG_JOY2TYPE],
  838.                            IA_Port2,          (Config[CFG_JOY1TYPE] == CFGJ1_MOUSE1)
  839.                                               ? IPT_NONE
  840.                                               : Config[CFG_JOY1TYPE],
  841.                            IA_KeyMap,         (ULONG) KeyMap,
  842.                            IA_P1AutoFireRate, (Config[CFG_JOY1TYPE] == CFGJ1_MOUSE1)
  843.                                               ? Config[CFG_JOY1AUTOFIRERATE]
  844.                                               : Config[CFG_JOY2AUTOFIRERATE],
  845.                            IA_P1BlueEmuTime,  (Config[CFG_JOY1TYPE] == CFGJ1_MOUSE1)
  846.                                               ? Config[CFG_JOY1BUTTONBTIME]
  847.                                               : Config[CFG_JOY2BUTTONBTIME],
  848.                            IA_P2AutoFireRate, Config[CFG_JOY1AUTOFIRERATE],
  849.                            IA_P2BlueEmuTime,  Config[CFG_JOY1BUTTONBTIME],
  850.                            IA_Window,         Video->Window,
  851.                            IA_RefreshHook,    (ULONG) &RefreshHook,
  852.                            IA_MenuHook,       (ULONG) &MenuHook,
  853.                            IA_IDCMPHook,      (ULONG) &IDCMPHook,
  854. #ifdef POWERUP
  855.                            IA_UseTicks,       TRUE,
  856. #endif
  857.                            TAG_END);
  858.  
  859.  
  860.       if(Inputs)
  861.       {
  862.         Width  = Video->Width;
  863.         Height = Video->Height;
  864.         Keys   = Inputs->Keys;
  865.         Port1  = Inputs->Ports[1];
  866.         Port2  = Inputs->Ports[0];
  867.         return(1);
  868.       }
  869.       else
  870.         ErrorRequest(MSG_FAILED_TO_ALLOCATE_INPUTS);
  871.     }
  872.     else
  873.       ErrorRequest(MSG_NOT_ENOUGH_MEMORY);
  874.  
  875.     if(DirectArray)
  876.       VFreeDirectArray(DirectArray);
  877.     if(PixelArray[0])
  878.       VFreePixelArray(PixelArray[0]);
  879. #ifdef POWERUP
  880.     if(PixelArray[1])
  881.       VFreePixelArray(PixelArray[1]);
  882. #endif
  883.  
  884.     FreeVideo(Video);
  885.   }
  886.   else
  887.   {
  888.     switch(VError)
  889.     {
  890.       case None:
  891.         break;
  892.         
  893.       case OutOfMemory:
  894.         ErrorRequest(MSG_NOT_ENOUGH_MEMORY);
  895.         break;
  896.  
  897.       case OpenScreenFailed:
  898.         ErrorRequest(MSG_FAILED_TO_OPEN_SCREEN);
  899.         break;
  900.  
  901.       case OpenWindowFailed:
  902.         ErrorRequest(MSG_FAILED_TO_OPEN_WINDOW);
  903.         break;
  904.     }
  905.   }
  906.  
  907.   return(0);
  908. }
  909.  
  910. void VideoClose(void)
  911. {
  912.   if(Video)
  913.   {
  914.     if(DirectArray)
  915.       VFreeDirectArray(DirectArray);
  916.     if(PixelArray[0])
  917.       VFreePixelArray(PixelArray[0]);
  918. #ifdef POWERUP
  919.     if(PixelArray[1])
  920.       VFreePixelArray(PixelArray[1]);
  921. #endif
  922.  
  923.     if(Inputs)
  924.       FreeInputs(Inputs);
  925.  
  926.     FreeVideo(Video);
  927.     Video = NULL;
  928.   }
  929. }
  930.  
  931. void InputUpdate(LONG wait)
  932. {
  933.   if(Inputs)
  934.   {
  935.     if(wait)
  936.       Wait(Inputs->SignalMask);
  937.  
  938.     IUpdate(Inputs);
  939.  
  940.     if(MenuSelect[ITEM_NEW])
  941.     {
  942.       MenuSelect[ITEM_NEW] = 0;
  943.  
  944.       NewGame              = 1;
  945.       Keys[OSD_KEY_ESC]    = 1;
  946.     }
  947.  
  948.     if(MenuSelect[ITEM_SAVE_ILBM])
  949.     {
  950.       MenuSelect[ITEM_SAVE_ILBM] = 0;
  951.       IDisable(Inputs);
  952.       SaveILBM();
  953.       ScreenToFront(Video->Window->WScreen);
  954.       ActivateWindow(Video->Window);
  955.       IEnable(Inputs);
  956.     }
  957.  
  958.     if(MenuSelect[ITEM_ABOUT])
  959.     {
  960.       MenuSelect[ITEM_ABOUT]  = 0;
  961.       IDisable(Inputs);
  962.       AboutGUI();
  963.       ScreenToFront(Video->Window->WScreen);
  964.       ActivateWindow(Video->Window);
  965.       IEnable(Inputs);
  966.     }
  967.  
  968.     if(MenuSelect[ITEM_QUIT])
  969.     {
  970.       MenuSelect[ITEM_QUIT] = 0;
  971.  
  972.       NewGame           = 0;
  973.       Keys[OSD_KEY_ESC] = 1;
  974.     }
  975.   }
  976. }
  977.  
  978. void ASM RefreshHandler(struct Hook *hook REG(a0))
  979. {
  980.   VRefresh(Video);
  981. }
  982.  
  983. void ASM MenuHandler(struct Hook *hook REG(a0), APTR null REG(a2), ULONG *itemnum REG(a1))
  984. {
  985.   MenuSelect[*itemnum]  = 1;
  986. }
  987.  
  988. void ASM IDCMPHandler(struct Hook *hook REG(a0), APTR null REG(a2), ULONG *imclass REG(a1))
  989. {
  990.   if(*imclass == IDCMP_CLOSEWINDOW)
  991.   {
  992.     NewGame           = 1;
  993.     Keys[OSD_KEY_ESC] = 1;
  994.   }
  995. }
  996.  
  997. STRPTR GetMessage(LONG id)
  998. {
  999.   return(GetString(&LocaleInfo, id));
  1000. }
  1001.  
  1002. /*
  1003. uclock_t uclock(void)
  1004. {
  1005.   static uclock_t old_uclock    = 0;
  1006.   uclock_t    new_uclock;
  1007.   struct timeval  tv;
  1008.  
  1009.   if(TimerBase)
  1010.   {
  1011.     GetSysTime(&tv);
  1012.     new_uclock  = (tv.tv_secs * UCLOCKS_PER_SEC) + (tv.tv_micro / (1000000 / UCLOCKS_PER_SEC));
  1013.     if(new_uclock == old_uclock)
  1014.       new_uclock++;
  1015.   }
  1016.   else
  1017.     new_uclock  = old_uclock + UCLOCKS_PER_SEC;
  1018.  
  1019.   old_uclock  = new_uclock;
  1020.  
  1021.   return(new_uclock);
  1022. }
  1023. */
  1024.  
  1025. void SaveILBM(void)
  1026. {
  1027.   BPTR new_dir;
  1028.   BPTR old_dir;
  1029.  
  1030.   if(!FileRequester)
  1031.     FileRequester = AllocAslRequest(ASL_FileRequest, NULL);
  1032.   
  1033.   if(FileRequester)
  1034.   {
  1035.     if(AslRequestTags(FileRequester,
  1036.                       ASLFR_DoSaveMode,  TRUE,
  1037.                       ASLFR_SleepWindow, TRUE,
  1038.                       ASLFR_TitleText,   (ULONG) GetMessage(MSG_MENU_SAVE_ILBM),
  1039.                       TAG_END))
  1040.     {
  1041.       new_dir = Lock(FileRequester->fr_Drawer, ACCESS_READ);
  1042.       
  1043.       if(new_dir)
  1044.       {
  1045.         old_dir = CurrentDir(new_dir);
  1046.         
  1047.         VSaveILBM(Video, FileRequester->fr_File);
  1048.         
  1049.         CurrentDir(old_dir);
  1050.         
  1051.         UnLock(new_dir);
  1052.       }
  1053.     }
  1054.   }
  1055. }
  1056.  
  1057. void ErrorRequest(LONG msg_id, ...)
  1058. {
  1059.   struct EasyStruct es;
  1060.   
  1061.   es.es_StructSize   = sizeof(struct EasyStruct);
  1062.   es.es_Flags        = 0;
  1063.   es.es_Title        = APPNAME;
  1064.   es.es_TextFormat   = GetMessage(msg_id);
  1065.   es.es_GadgetFormat = GetMessage(MSG_OK);
  1066.   
  1067.   EasyRequestArgs(NULL, &es, NULL, &((&msg_id)[1]));
  1068. }
  1069.